//
//  IMSocketManager.m
//  MyChatDemo
//
//  Created by DragonYao on 2017/10/9.
//  Copyright © 2017年 DragonYao. All rights reserved.
//

#import "IMSocketManager.h"
#import <sys/types.h>
#import <arpa/inet.h>
#import <netinet/in.h>
#import <sys/socket.h>

@interface IMSocketManager ()

@property (nonatomic, assign) int clientScoket;//客户端

@end

@implementation IMSocketManager

+ (IMSocketManager *)sharedManager {
    static IMSocketManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self initSocket];
    }
    return self;
}

//初始化
- (void)initSocket {
    //创建socket,如果之前有了连接，则先断开连接
    if (_clientScoket != 0) {
        [self disconnectServer];
        _clientScoket = 0;
    }
    
    //创建客户端socket
    _clientScoket = CreateClientSocket();
    //服务器IP
    const char *serverIp = "127.0.0.1";
    //服务器端口
    int serverPort = 9999;
    int connectStatus = ConnectedToServer(_clientScoket, serverIp, serverPort);
    if (connectStatus == 0) {
        NSLog(@"connect to server error");
        return ;
    }
    NSLog(@"connect to server success");
}

/**
 *  创建与服务器的连接
 */
- (void)connectServer {
    [self initSocket];
}

/**
 *  断开与服务器的连接
 */
- (void)disconnectServer {
    close(self.clientScoket);
}

/**
 *  发送消息
 */
- (void)sendMessage:(NSString *)message {
    const char *send_message = [message UTF8String];
    send(self.clientScoket, send_message, strlen(send_message) + 1, 0);
}

#pragma mark - Helper Method
//创建客户端socket
static int CreateClientSocket() {
    //参数1:addressFamily IPv4(AF_INET) 或 IPv6(AF_INET6)
    //参数2:type 表示socket的类型，通常是流stream(SOCK_STREAM)或数据报文datagram(SOCK_DGRAM)
    //第三个参数 protocol 参数通常设置为0，
    //以便让系统自动为选择我们合适的协议，对于 stream socket 来说会是 TCP 协议(IPPROTO_TCP)，而对于 datagram来说会是 UDP 协议(IPPROTO_UDP)。
    int clientSocket = 0;
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    return clientSocket;
}

//连接服务器
static int ConnectedToServer(int clientSocket, const char *serverIp, int serverPort) {
    //生成sockaddr_in结构体
    struct sockaddr_in sockAddr = {0};
    sockAddr.sin_len = sizeof(sockAddr);
    sockAddr.sin_family = AF_INET;
    //inet_aton是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP地址
    //如果这个函数成功，函数的返回值非零，如果输入地址不正确则会返回零。
    int addr_status = inet_aton(serverIp, &sockAddr.sin_addr);
    if (addr_status == 0) {
        printf("网址不正确");
    }
    //htons是将整型变量从主机字节顺序转变成网络字节顺序，赋值端口号
    sockAddr.sin_port = htons(serverPort);
    //用scoket和服务端地址，发起连接。
    //客户端向特定网络地址的服务器发送连接请求，连接成功返回0，失败返回 -1。
    //注意：该接口调用会阻塞当前线程，直到服务器返回。
    if (connect(clientSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == 0) {
        return clientSocket;
    }
    return 0;
}

- (void)reciveMsgFromNewThread {
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(reciveMsgAction:) object:nil];
    [thread start];
}

- (void)reciveMsgAction:(NSThread *)thread {
    SLog(@"current thread : %@", thread);
    while (1) {
        char recv_message[1024] = {0};
        recv(self.clientScoket, recv_message, sizeof(recv_message), 0);
        printf("recive: %s\n", recv_message);
    }
}


@end
